require 'depac-common/constants'
require 'depac-common/log'
require 'yaml'
require 'pp'

validate_yml_file = Depac::CloudDeploymentConstants::VALIDATE_FILE_PATH
validate_yml_path = Gem::Specification.find_by_name(Depac::CloudDeploymentConstants::CLOUD_DEPL_GEM_NAME).gem_dir + validate_yml_file
$validate = YAML.load_file(validate_yml_path)

class EnvironmentConfiguration

  
  # Initialize the input config file.
  def initialize(fileName)
    if(fileName.kind_of?(String)) 
        if (File.exists?(fileName))
          @envConfig = YAML.load_file(fileName)
        else
          raise "ERROR: File '#{fileName}' does not exist."
        end
      else
          @envConfig = fileName
      end
      #downCaseRoles()
      #validateConfig()
    
      rescue => error_reason
          Depac::Log.write("ERROR", "#{error_reason}")
          exit
  end
  
  def downCaseRoles()
    typeArr = getEnvironmentTypes()
  
    typeArr.each do |type|
      if(@envConfig[type] != nil)
        @envConfig[type].each do |config|
          role = config[Depac::CloudDeploymentConstants::ROLE]
          config[Depac::CloudDeploymentConstants::ROLE] = role.downcase
        end
      end
    end
  end
  
  def validateConfig()
    inputRoleArr = getRoleArray()
    
    inputRoleArr.each do |inputRole|
      found = false
      allowedRolesArr = $validate[Depac::CloudDeploymentConstants::ROLES]
      
      allowedRolesArr.each do |allowedRole|
        if(inputRole == allowedRole)
          found = true
        end
      end
      
      if(found == false)
        pp "ERROR: The role #{inputRole} is not valid."
        exit
      end
    end
  end
  
  # Get the environment configuration.
  def getEnvironmentConfiguration()
    return @envConfig
  end
  
  # Set the environment configuration.
  def setEnvironmentConfiguration(config)
    @envConfig = config
  end
  
  # Get the database configuration.
  def getDatabaseConfigurationByType(type)
    if (@databaseConfig == nil)
      @databaseConfig = getNodeConfigurationByRoleAndType(Depac::CloudDeploymentConstants::ROLE_DATABASE, type)
    end
    return @databaseConfig
  end
  
  # Get the appserver configuration.
  def getAppServerConfigurationByType(type)
    if (@appServerConfig == nil)
      @appServerConfig = getNodeConfigurationByRoleAndType(Depac::CloudDeploymentConstants::ROLE_APPSERVER, type)
    end
    return @appServerConfig
  end
  
  # Get the foundation configuration.
  def getFoundationConfigurationByType(type)
    if (@foundationConfig == nil)
      @foundationConfig = getNodeConfigurationByRoleAndType(Depac::CloudDeploymentConstants::ROLE_FOUNDATION, type)
    end
    return @foundationConfig
  end
  
  # Get the environment name.
  def getEnvironmentName()
    if (@envName == nil)
      @envName = @envConfig[Depac::CloudDeploymentConstants::ENVIRONMENT];
    end
    
    return @envName
  end
  
  # TODO - Depricated - to be removed
  # Get the node level configuration based on role.
  def getNodeConfigurationByRole(role)
    nodeConfig = nil
    @envConfig[$nodes].each do |config|
      if (config[Depac::CloudDeploymentConstants::ROLE].eql? role)
        nodeConfig = config
      end
    end
    return nodeConfig
  end
  
  # Get the node level configuration based on role and type.
  def getNodeConfigurationByRoleAndType(role, type)
    nodeConfig = nil
    if(@envConfig[type] != nil)
      @envConfig[type].each do |config|
        if (config[Depac::CloudDeploymentConstants::ROLE].eql? role)
          nodeConfig = config
        end
      end
    else
      @envConfig[:vms].each do |config|
        if (config[Depac::CloudDeploymentConstants::ROLE].eql? role)
                 nodeConfig = config
        end
      end
    end
    return nodeConfig
  end
  
  # Get VM configure by role
  def getVMConfigByRole(role)
     vmconfig=nil
     @envConfig[:vms].each do |config|
        if (config[Depac::CloudDeploymentConstants::ROLE].eql? role)
              vmconfig = config['vmconfig']
              break
        end 
     end
     return vmconfig
  end
  
  # Get the softlayer credentials.
  def getSoftLayerCredentials()
          Depac::Log.fatal_exit("'apikeyloc' needs to be specified in the deployment configuration file") unless @envConfig['apikeyloc']
          apikeyfile = File.expand_path(@envConfig['apikeyloc'])
          Depac::Log.fatal_exit("'apikeyloc' file was not found. Configured value: #{apikeyfile}") unless File.exists?(apikeyfile)
     return YAML.load_file(apikeyfile)
  end
  
# Get the softlayer credentials.
  def getCloudCredentials()
          
          apikeyfile = File.expand_path(@envConfig['apikeyloc']) 
          apikeyfile = File.expand_path(@envConfig[:system]['apikeyloc']) if apikeyfile == nil   

          if apikeyfile == nil
               Depac::Log.fatal_exit("'apikeyloc' needs to be specified in the deployment configuration file")
          end

          Depac::Log.fatal_exit("'apikeyloc' file was not found. Configured value: #{apikeyfile}") unless File.exists?(apikeyfile)
     return YAML.load_file(apikeyfile)
  end
  
  # TODO
  # Get the array of all Roles
  def getRoleArray()
       roleArray = Array.new
        Depac::Log.write("INFO", "vms is : #{@envConfig[:vms]}")
        @envConfig[:vms].each do |config|
          roleArray.push(config[Depac::CloudDeploymentConstants::ROLE])
        end
          
        return roleArray
  end
  
  # Get the array of all Roles withing a environment
  def getRoleArrayByType(type)
    roleArray = Array.new
    if(@envConfig[type] != nil)
      @envConfig[type].each do |config|
        roleArray.push(config[Depac::CloudDeploymentConstants::ROLE])
      end
    end
    return roleArray
  end
  
  # TODO
  # Get Hostname:IP mapping for a role
  def getHostnameIPMapByRoleAndType(role, type)
    hostIPArray = Array.new
    nodeConfig = nil
    nodeConfig = getNodeConfigurationByRoleAndType(role,type)
    if (nodeConfig != nil)
      hostIPArray.push(nodeConfig[Depac::CloudDeploymentConstants::NODE_INFO])
    end
    return hostIPArray
  end
  
# TODO
  # Get Hostname:IP mapping for a role
  def getHostnameIPMapByRoleAndType(role, type)
    hostIPArray = Array.new
    nodeConfig = nil
    nodeConfig = getNodeConfigurationByRoleAndType(role,type)
    if (nodeConfig != nil)
      hostIPArray.push(nodeConfig[Depac::CloudDeploymentConstants::NODE_INFO])
    end
    return hostIPArray
  end
  
   def getNodeConfigurationByRole(role)    
           roleConfig = nil
           @envConfig[:vms].each do | _roleConfig|
                  if _roleConfig[Depac::CloudDeploymentConstants::ROLE].eql? role
                        roleConfig = _roleConfig
                  end 
           end        
           return roleConfig
   end
  
  # return the node configuration by type - authoring or runtime
  def getNodeConfigurationByType(type)
    return @envConfig[type]
  end
  
  # Returns the build label from the configuration
  def getBuildLabel()
    return @envConfig[Depac::CloudDeploymentConstants::BUILD_LABEL];
  end
end

#configObject = EnvironmentConfiguration.new("input.yml")
#pp configObject.getDatabaseConfiguration()
#pp configObject.getAppServerConfiguration()

#pp configObject.getNodeConfigurationByRole("appServer1")


#pp readEnvironmentConfig("input.yml");

#pp $envConfig